﻿/*
* 创建者：LIYINFAI
* 创建时间：2023/10/15 11:40:00
* 描述：
* --------------------------------------
* 修改说明：
* --------------------------------------
*/
using Newtonsoft.Json;
using Org.BouncyCastle.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace CommonLibrary
{
    /// <summary>
    /// 扫码枪串口配置
    /// </summary>
    public class MultiScanComParam : ComParameter
    {
        /// <summary>
        /// 结果地址
        /// </summary>
        [Description("结果地址")]
        [JsonProperty(PropertyName = "PLCEntities")]
        public List<ScanPLCEntity> PLCEntities = new List<ScanPLCEntity>();
        /// <summary>
        /// 触发地址
        /// </summary>
        [Description("触发地址")]
        [JsonProperty(PropertyName = "TriggerAddress")]
        public string TriggerAddress { get; set; } = string.Empty;
        /// <summary>
        /// 扫码命令
        /// </summary>
        [Description("扫码命令")]
        [JsonProperty(PropertyName = "Command")]
        public string Command { get; set; } = "LON\r\n";
        /// <summary>
        /// 用于显示
        /// </summary>
        [JsonIgnore]
        public string CommandText
        {
            get
            {
                return string.IsNullOrWhiteSpace(this.Command) ? string.Empty : this.Command.Replace("\r", "\\r").Replace("\n", "\\n");
            }
        }
        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return CommonHelper.GetObjectString(this);
        }
    }
    /// <summary>
    /// 扫码枪TCP配置
    /// </summary>
    public class MultiScanTcpParam : TcpParameter
    {
        /// <summary>
        /// 结果地址
        /// </summary>
        [Description("结果地址")]
        [JsonProperty(PropertyName = "PLCEntities")]
        public List<ScanPLCEntity> PLCEntities = new List<ScanPLCEntity>();
        /// <summary>
        /// 触发地址
        /// </summary>
        [Description("触发地址")]
        [JsonProperty(PropertyName = "TriggerAddress")]
        public string TriggerAddress { get; set; } = string.Empty;
        /// <summary>
        /// 扫码命令
        /// </summary>
        [Description("扫码命令")]
        [JsonProperty(PropertyName = "Command")]
        public string Command { get; set; } = "LON\r\n";
        /// <summary>
        /// 用于显示
        /// </summary>
        [JsonIgnore]
        public string CommandText
        {
            get
            {
                return string.IsNullOrWhiteSpace(this.Command) ? string.Empty : this.Command.Replace("\r", "\\r").Replace("\n", "\\n");
            }
        }
        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return CommonHelper.GetObjectString(this);
        }
    }
    /// <summary>
    /// 自定义处理代理
    /// </summary>
    /// <param name="scanHelper"></param>
    /// <param name="barcode"></param>
    /// <param name="checkResult"></param>
    /// <param name="scanTime"></param>
    /// <returns></returns>
    public delegate (short mesResult, bool plcOptFinished) CustomMultiScanHelperJobDelegate(MultiScanHelper scanHelper, string[] barcode, EBarcodeCheckResult[] checkResult, string[] scanTime);
    /// <summary>
    /// 扫码枪帮助类
    /// </summary>
    public class MultiScanHelper : BaseHelper
    {
        /// <summary>
        /// TCP配置文件
        /// </summary>
        static string autoTcpMultiScanConfigPath = Path.Combine(CommonHelper.COMMON_CONFIG_DIR, "MultiScanTCPConfig.json");
        /// <summary>
        /// 串口配置文件（自动扫码枪）
        /// </summary>
        static string autoComMultiScanConfigPath = Path.Combine(CommonHelper.COMMON_CONFIG_DIR, "MultiScanComConfig.json");

        #region tcp auto
        /// <summary>
        /// 获取TCP扫码枪配置，返回List对象
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static List<MultiScanTcpParam> GetAutoMultiScanTCPConfig()
        {
            return CommonHelper.GetJsonListFromFile<MultiScanTcpParam>(autoTcpMultiScanConfigPath);
        }
        /// <summary>
        /// 保存TCP配置内容
        /// </summary>
        /// <param name="list"></param>
        public static void SaveAutoMultiScanTCPConfig(List<MultiScanTcpParam> list)
        {
            CommonHelper.SaveToJsonFile(list, autoTcpMultiScanConfigPath);
        }
        #endregion
        #region auto com
        /// <summary>
        /// 获取串口配置内容（自动扫码枪）
        /// </summary>
        /// <returns></returns>
        public static List<MultiScanComParam> GetAutoMultiScanComConfig()
        {
            return CommonHelper.GetJsonListFromFile<MultiScanComParam>(autoComMultiScanConfigPath);
        }
        /// <summary>
        /// 保存串口配置内容（自动扫码枪）
        /// </summary>
        /// <param name="list"></param>
        public static void SaveAutoMultiScanComConfig(List<MultiScanComParam> list)
        {
            CommonHelper.SaveToJsonFile(list, autoComMultiScanConfigPath);
        }
        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        public MultiScanHelper()
        {
        }
        #region 每个Helper特定的参数
        /// <summary>
        /// 通讯超时时间，默认1000毫秒
        /// </summary>
        public override int CommunicationTimeout => BusinessConfig.Instance().ScanTimeout;
        /// <summary>
        /// 扫码次数
        /// </summary>
        public int RepeatTimes => BusinessConfig.Instance().ScanRepeatTimes;
        /// <summary>
        /// 错误barcode
        /// </summary>
        public static readonly string ERROR_BARCODE = "ERROR";
        /// <summary>
        /// 是否需要检查长度
        /// </summary>
        public bool IsNeedCheckBarcodeLength => BusinessConfig.Instance().IsCheckBarcodeLength;
        /// <summary>
        /// 验证的标准长度值
        /// </summary>
        public int BarcodeLegth => BusinessConfig.Instance().BarcodeLength;
        /// <summary>
        /// 是否需要检查前缀
        /// </summary>
        public bool IsNeedCheckBarcodePrev => BusinessConfig.Instance().IsCheckBarcodePrev;
        /// <summary>
        /// 验证的标准前缀值
        /// </summary>
        public string StartValue => BusinessConfig.Instance().BarcodePrev;
        /// <summary>
        /// 是否需要检查后缀
        /// </summary>
        public bool IsNeedCheckBarcodeLast { get; set; } = false;
        /// <summary>
        /// 验证的标准后缀值
        /// </summary>
        public string EndValue { get; set; } = string.Empty;
        /// <summary>
        /// 开始命令
        /// </summary>
        public string StartCommand { get; set; } = "LON\r\n";
        /// <summary>
        /// 结束命令
        /// </summary>
        public string EndCommand { get; set; } = string.Empty;//"LOFF\r\n";
        #endregion
        /// <summary>
        /// PLC业务
        /// </summary>
        /// <param name="barcodes"></param>
        /// <param name="checkResults"></param>
        /// <param name="plcEntities"></param>
        private void BusinessHandler(ref string[] barcodes, ref EBarcodeCheckResult[] checkResults, List<ScanPLCEntity> plcEntities)
        {
            if (plcEntities != null && plcEntities.Count > 0 && barcodes != null && barcodes.Length > 0 && checkResults != null && checkResults.Length > 0)
            {
                for (int i = 0; i < plcEntities.Count; i++)
                {
                    if (i < barcodes.Length)
                    {
                        var checkResult = EBarcodeCheckResult.NG;
                        var plcEntity = plcEntities[i];
                        var barcode = barcodes[i];
                        var param = new ScanExcuteEntity()
                        {
                            PlcEntity = plcEntity,
                            Barcode = barcode,
                            ScanTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                        };
                        #region Barcode
                        param = CommonHelper.GetJson(PluginManager.Instance.Excute(this.Name, "SCAN_BARCODE", CommonHelper.GetJsonString(param, Formatting.None)), param);
                        checkResult = CommonHelper.GetEnumByRealValue(param.ScanResult, EBarcodeCheckResult.NG);
                        string scanTime = param.ScanTime;
                        #endregion
                        #region  MES
                        param.MESResult = short.Parse(PluginManager.Instance.Excute(this.Name, "SCAN_MES", CommonHelper.GetJsonString(param, Formatting.None)));
                        #endregion
                        #region  PLC
                        PluginManager.Instance.Excute(this.Name, "SCAN_PLC", CommonHelper.GetJsonString(param, Formatting.None));
                        #endregion

                        if (i < checkResults.Length)
                        {
                            checkResults[i] = checkResult;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 串口方式获取条码
        /// </summary>
        /// <returns></returns>
        private string GetComBarcode()
        {
            string barcode = "";
            if (this.IsConnected)
            {
                try
                {
                    this.SerialSendString(this.StartCommand);
                    barcode = this.GetSerialReturnUTF8String();
                    if (!string.IsNullOrWhiteSpace(this.EndCommand))
                    {
                        this.SerialSendString(this.EndCommand);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
            }
            return barcode;
        }
        /// <summary>
        /// TCP方式获取条码
        /// </summary>
        /// <returns></returns>
        private string GetTcpBarcode()
        {
            string barcode = "";
            if (this.IsConnected)
            {
                try
                {
                    this.TcpSend(Encoding.UTF8.GetBytes(this.StartCommand));
                    barcode = this.TcpReceiveString();
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
            }
            return barcode;
        }
        /// <summary>
        /// 获取条码
        /// </summary>
        /// <returns></returns>
        public string GetBarcode()
        {
            string result = this.CommunicationType == ECommunicationType.SERIAL ? GetComBarcode() : GetTcpBarcode();
            LogHelper.Info($"【{this.Name}】获取条码：{result}");
            return result;
        }
        /// <summary>
        /// 切分条码的字符
        /// </summary>
        private char mSplitItemValue = ',';
        /// <summary>
        /// 切分条码与索引的字符
        /// </summary>
        private char mSplitItemIndexValue = ':';
        /// <summary>
        /// 业务处理
        /// </summary>
        /// <param name="handlerName"></param>
        /// <param name="handlerType"></param>
        /// <param name="otherAddress"></param>
        /// <param name="otherData"></param>
        public override void RealHandler(string handlerName, EHandlerType handlerType, object otherAddress, object otherData)
        {
            this.RealShowMessage($"【{this.Name}】{handlerName}");
            List<ScanPLCEntity> entities = otherAddress as List<ScanPLCEntity>;
            if (entities != null && entities.Count > 0)
            {
                int count = entities.Count;
                EBarcodeCheckResult[] checkResults = new EBarcodeCheckResult[count];
                string[] barcodes = new string[count];
                for (int i = 0; i < count; i++)
                {
                    checkResults[i] = EBarcodeCheckResult.NG;
                    barcodes[i] = ERROR_BARCODE;
                }

                Stopwatch stopwatch = Stopwatch.StartNew();
                if (this.IsConnected)
                {
                    try
                    {
                        string barcodeResult = string.Empty;
                        Stopwatch stopwatchBarcode = Stopwatch.StartNew();
                        for (var i = 0; i < this.RepeatTimes; i++)
                        {
                            barcodeResult = GetBarcode();
                            //如果为空或错误条码，重新扫码
                            if (!string.IsNullOrWhiteSpace(barcodeResult)
                                && ((count == 1 && !barcodeResult.ToUpper().Equals(ERROR_BARCODE)) || (count > 1 && barcodeResult.Contains(this.mSplitItemValue))))
                            {
                                break;
                            }
                        }
                        stopwatchBarcode.Stop();
                        LogHelper.Info($"【{this.Name}】【统计】扫码时间耗时：{stopwatchBarcode.ElapsedMilliseconds} 毫秒");
                        if (!string.IsNullOrWhiteSpace(barcodeResult))
                        {
                            string[] items = barcodeResult.Split(this.mSplitItemValue);
                            foreach (var item in items)
                            {
                                string itemString = string.IsNullOrWhiteSpace(item) ? string.Empty : CommonHelper.RemoveEnterString(item);
                                if (itemString.Contains(this.mSplitItemIndexValue))
                                {
                                    int index = itemString.IndexOf(this.mSplitItemIndexValue);
                                    string bString = itemString.Substring(0, index);
                                    string iString = itemString.Substring(index + 1);
                                    int no = -1;
                                    if (int.TryParse(iString, out no) && no <= count)
                                    {
                                        barcodes[no - 1] = bString;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                    finally
                    {
                        BusinessHandler(ref barcodes, ref checkResults, entities);
                    }
                }
                stopwatch.Stop();
                bool isOk = true;
                List<string> checkResultDesc = new List<string>();
                foreach (var item in checkResults)
                {
                    checkResultDesc.Add($"{item}");
                    if (item != EBarcodeCheckResult.OK)
                    {
                        isOk = false;
                    }
                }
                LogHelper.Info($"【{this.Name}】【统计】自动扫码耗时：{stopwatch.ElapsedMilliseconds} 毫秒");
                this.RealShowMessage($"【{this.Name}】自动扫码，耗时：{stopwatch.ElapsedMilliseconds} 毫秒，扫码值：{string.Join(",", barcodes)}，扫码结果：{string.Join(",", checkResultDesc)}。", isOk);

            }
        }
    }
}
